package com.fengye.provider;

import com.fengye.common.IPHelper;
import com.fengye.model.ProviderService;
import com.fengye.register.RegisterCenter;
import com.fengye.register.RegisterCenter4Provider;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import sun.print.resources.serviceui_ja;

import java.lang.reflect.Method;
import java.util.List;

/**
 * 服务Bean 发布入口，集成进spring
 * @Author fengye
 * @Date 2023/2/14 13:15
 **/
public class ProviderFactoryBean implements FactoryBean, InitializingBean {

    /** 服务接口 */
    private Class<?> serviceItf;

    /** 服务实现 */
    private Object serviceObject;

    /** 服务端口 */
    private int serverPort;
    /** 服务超时时间 */
    private int timeout = 3000;

    /**服务代理对象 */
    private Object serviceProxyObject;
    /** 服务提供者唯一标识 */
    private String appKey;
    /** 服务分组组名 */
    private String groupName = "default";
    /** 服务提供者权重，负载均衡用，默认1，范围[1-100] */
    private int weight = 1;
    /** 服务端线程数，默认10个线程 */
    private int workerThreads = 10;

    @Override
    public Object getObject() throws Exception {
        return serviceProxyObject;
    }

    @Override
    public Class<?> getObjectType() {
        return serviceItf;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 启动Netty服务
        NettyServer.singleton().start(serverPort);
        // 构建服务信息，并注册到注册中心
        List<ProviderService> providerServiceList = buildProviderServiceInfos();
        RegisterCenter4Provider registerCenter4Provider = RegisterCenter.singleton();
        registerCenter4Provider.registerProvider(providerServiceList);
    }

    /**
     * 构建服务信息
     * @return
     */
    private List<ProviderService> buildProviderServiceInfos() {
        List<ProviderService> providerServiceList = Lists.newArrayList();
        Method[] methods = serviceObject.getClass().getDeclaredMethods();
        for (Method method : methods) {
            ProviderService providerService = new ProviderService();
            providerService.setServiceItf(serviceItf);
            providerService.setServiceObject(serviceObject);
            providerService.setServerIp(IPHelper.localIp());
            providerService.setServerPort(serverPort);
            providerService.setTimeout(timeout);
            providerService.setServiceMethod(method);
            providerService.setWeight(weight);
            providerService.setWorkerThread(workerThreads);
            providerService.setAppKey(appKey);
            providerService.setGroupName(groupName);
            providerServiceList.add(providerService);
        }
        return providerServiceList;
    }

    public Class<?> getServiceItf() {
        return serviceItf;
    }

    public void setServiceItf(Class<?> serviceItf) {
        this.serviceItf = serviceItf;
    }

    public Object getServiceObject() {
        return serviceObject;
    }

    public void setServiceObject(Object serviceObject) {
        this.serviceObject = serviceObject;
    }

    public int getServerPort() {
        return serverPort;
    }

    public void setServerPort(int serverPort) {
        this.serverPort = serverPort;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public Object getServiceProxyObject() {
        return serviceProxyObject;
    }

    public void setServiceProxyObject(Object serviceProxyObject) {
        this.serviceProxyObject = serviceProxyObject;
    }

    public String getAppKey() {
        return appKey;
    }

    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getWorkerThreads() {
        return workerThreads;
    }

    public void setWorkerThreads(int workerThreads) {
        this.workerThreads = workerThreads;
    }
}
